package com.geovis.emergency.spd.biz.pc.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.geovis.common.mybatis.page.PageParam;
import com.geovis.common.mybatis.page.PageResult;
import com.geovis.emergency.spd.biz.pc.mapper.PcDisasterMapper;
import com.geovis.emergency.spd.biz.pc.service.IPcDisasterEventService;
import com.geovis.emergency.spd.biz.pc.service.IPcDisasterService;
import com.geovis.emergency.spd.biz.pc.service.IPcDrillDisasterService;
import com.geovis.emergency.spd.biz.pc.service.IPcDrillService;
import com.geovis.emergency.spd.entity.pc.entity.*;
import com.geovis.emergency.spd.entity.pc.pojo.constant.PcDisasterConstant;
import com.geovis.emergency.spd.entity.pc.pojo.constant.PcDrillConstant;
import com.geovis.emergency.spd.entity.pc.pojo.dto.PcDisasterQueryDTO;
import com.geovis.emergency.spd.entity.pc.pojo.dto.PcDisasterSaveDTO;
import com.geovis.emergency.spd.entity.pc.pojo.dto.PcDisasterUpdateDTO;
import com.geovis.emergency.spd.entity.pc.pojo.enums.StatusEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 应急预案指挥模块-灾害管理 服务实现类
 * </p>
 *
 * @author Lonsho
 * @since 2022-06-08
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class PcDisasterServiceImpl extends ServiceImpl<PcDisasterMapper, PcDisaster> implements IPcDisasterService {
    @Autowired
    @Lazy
    private IPcDrillService pcDrillService;
    @Autowired
    @Lazy
    private IPcDrillDisasterService pcDrillDisasterService;

    private final IPcDisasterEventService disasterEventService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savePcDisaster(PcDisasterSaveDTO saveDTO) {
        PcDisaster pcDisaster = new PcDisaster();
        BeanUtil.copyProperties(saveDTO, pcDisaster);
        if (StrUtil.isEmpty(pcDisaster.getDataStatus())){
            pcDisaster.setDataStatus(StatusEnum.TRUE.getCode());
        }
        Long count = baseMapper.selectCount(Wrappers.lambdaQuery());
        if(ObjectUtil.isNotNull(count)){
            //序号自动+1
            pcDisaster.setIdx(count.intValue()+1);
        }else {
            pcDisaster.setIdx(1);
        }
        //台风类型，台风id不能为空
        Assert.isFalse(PcDisasterConstant.TYPHOON.equals(saveDTO.getType()) && StrUtil.isBlank(saveDTO.getTyphoonNo()), "请关联台风事件");
        pcDisaster.setTyphoonNo(saveDTO.getTyphoonNo());
        baseMapper.insert(pcDisaster);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePcDisaster(PcDisasterUpdateDTO updateDTO) {
        PcDisaster pcDisaster = baseMapper.selectById(updateDTO.getId());
        BeanUtil.copyProperties(updateDTO, pcDisaster);
        //台风类型，台风id不能为空
        Assert.isFalse(PcDisasterConstant.TYPHOON.equals(updateDTO.getType()) && StrUtil.isBlank(updateDTO.getTyphoonNo()), "请关联台风事件");
        baseMapper.updateById(pcDisaster);
    }
    @Override
    public PageResult<PcDisaster> listPage(PageParam<PcDisasterQueryDTO> pageParam) {
        PcDisasterQueryDTO queryDTO = pageParam.getQuery();
        IPage<PcDisaster> page = pageParam.buildPage();
        page(page, getWrapper(queryDTO));
        if(queryDTO.getIsContainEvent())
        {
            List<PcDisaster> result= page.getRecords().stream().filter(pcDisaster-> {
                List<PcDisasterEvent> disasterEvents = disasterEventService.list(Wrappers.lambdaQuery(PcDisasterEvent.class).eq(PcDisasterEvent::getPcDisasterId, pcDisaster.getId()));
                if (CollectionUtils.isEmpty(disasterEvents))
                {
                    return false;
                }
                return true;
            }).collect(Collectors.toList());
            page.setRecords(result);
        }
        return new PageResult<>(page);
    }

    @Override
    public List<PcDisaster> getList(PcDisasterQueryDTO queryDTO) {
        return list(getWrapper(queryDTO));
    }

    @Override
    public Boolean checkDisasterInDrill(List<String> ids,Boolean containEndDrill) {
        List<String> status = new ArrayList<>();
        status.add(PcDrillConstant.STATUS_DOING);
        status.add(PcDrillConstant.STATUS_PREPARE);
        if(containEndDrill)
        {
            status.add(PcDrillConstant.STATUS_COMPLETE);
        }
        List<PcDrill> pcDrills = pcDrillService.list(Wrappers.lambdaQuery(PcDrill.class).in(PcDrill::getStatus, status));
        if (CollectionUtils.isEmpty(pcDrills))
        {
            return false;
        }
        List<String> pcDrillIds=pcDrills.stream().map(PcDrill::getId).collect(Collectors.toList());
        List<PcDrillDisaster> drillDisasters=pcDrillDisasterService.list(Wrappers.lambdaQuery(PcDrillDisaster.class).in(PcDrillDisaster::getPcDrillId, pcDrillIds).in(PcDrillDisaster::getPcDisasterId,ids));
        if(!CollectionUtils.isEmpty(drillDisasters))
        {
            return true;
        }
        return false;
    }

    private LambdaQueryWrapper<PcDisaster> getWrapper(PcDisasterQueryDTO queryDTO) {
        LambdaQueryWrapper<PcDisaster> wrapper = Wrappers.<PcDisaster>lambdaQuery().orderByDesc(PcDisaster::getCreateTime);
        if (ObjectUtil.isNotEmpty(queryDTO)) {
            wrapper.like(StrUtil.isNotBlank(queryDTO.getName()),PcDisaster::getName,queryDTO.getName());
            wrapper.eq(StrUtil.isNotBlank(queryDTO.getType()),PcDisaster::getType,queryDTO.getType());
            wrapper.in(ObjectUtil.isNotEmpty(queryDTO.getTypeList()),PcDisaster::getType,queryDTO.getTypeList());
            wrapper.eq(StrUtil.isNotBlank(queryDTO.getEventType()),PcDisaster::getEventType,queryDTO.getEventType());
            wrapper.eq(StrUtil.isNotBlank(queryDTO.getDataStatus()),PcDisaster::getDataStatus,queryDTO.getDataStatus());
        }
        return wrapper;
    }
}
